package core.security;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import dao.security.UsrAuthResDao;

public class MyInvocationSecurityMetadataSourceService  implements FilterInvocationSecurityMetadataSource {

	private UsrAuthResDao authResDao;

	private UrlMatcher urlMatcher = new AntUrlPathMatcher();

	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public MyInvocationSecurityMetadataSourceService() {
		loadResourceDefine();
	}

	private void loadResourceDefine() {
		ApplicationContext context = new ClassPathXmlApplicationContext(
				"classpath:applicationContext.xml");

		SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
		Session session = sessionFactory.openSession();

		// 在Web服务器启动时，提取系统中的所有权限。
		@SuppressWarnings("unchecked")
		List<String> query = session.createSQLQuery("select authname from usr_auth").list();

		/*
		 * 应当是资源为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
		 * sparta
		 */
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

		for (String auth : query) {
			ConfigAttribute ca = new SecurityConfig(auth);

			/*String querysql="select b.reslink "
					+ "from usr_auth_res a, usr_res b, usr_auth c "
					+ "where a.resid = b.resid "
					+ "and a.authid=c.authid and c.authname='"
					+ auth + "'";*/
			//以上是将权限表与资源表分开，以下是合并
			String querysql="select c.reslink from usr_auth c where c.authname='"+ auth + "'";
			
			@SuppressWarnings("unchecked")
			List<String> query1 = session.createSQLQuery(querysql).list();

			String url=null;
			for (String res : query1) {
				url = res;
				//判断资源文件和权限的对应关系，如果已经存在相关的资源url，则要通过该url为key提取出权限集合，将权限增加到权限集合中。
				if (resourceMap.containsKey(url)) {
					Collection<ConfigAttribute> value = resourceMap.get(url);
					value.add(ca);
					resourceMap.put(url, value);
				} else {
					Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
					atts.add(ca);
					resourceMap.put(url, atts);
				}

			}

		}

	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	// 根据URL，找到相关的权限配置。
	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {

		// object 是一个URL，被用户请求的url。
		String url = ((FilterInvocation) object).getRequestUrl();
		
        int firstQuestionMarkIndex = url.indexOf("?");

        if (firstQuestionMarkIndex != -1) {
            url = url.substring(0, firstQuestionMarkIndex);
        }
		Iterator<String> ite = resourceMap.keySet().iterator();

		String resURL=null;
		while (ite.hasNext()) {
			resURL = ite.next();
			if (urlMatcher.pathMatchesUrl(url, resURL)) {
				return resourceMap.get(resURL);
			}
		}

		return null;
	}

	@Override
	public boolean supports(Class<?> arg0) {
		return true;
	}

	public UsrAuthResDao getAuthResDao() {
		return authResDao;
	}

	public void setAuthResDao(UsrAuthResDao authResDao) {
		this.authResDao = authResDao;
	}

}
